package 其他;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Description
 *
 * @Author: Heiffeng
 * @Date: 2022/4/2 23:29
 */
public class 孙博通加密算法 {

    static Map<String,Integer> DICT = new HashMap<>();
    static{
        DICT.put("a",1);
        DICT.put("b",2);
        DICT.put("c",3);
        DICT.put("d",4);
        DICT.put("e",5);
        DICT.put("f",6);
        DICT.put("g",7);
        DICT.put("h",8);
        DICT.put("i",9);
        DICT.put("j",10);
        DICT.put("k",11);
        DICT.put("l",12);
        DICT.put("m",13);
        DICT.put("n",14);
        DICT.put("o",15);
        DICT.put("p",16);
        DICT.put("q",17);
        DICT.put("r",18);
        DICT.put("s",19);
        DICT.put("t",20);
        DICT.put("u",21);
        DICT.put("v",22);
        DICT.put("w",23);
        DICT.put("x",24);
        DICT.put("y",25);
        DICT.put("z",26);
    }

    public static void main(String[] args) {
        // 待加密字符串
        String message = "Hello world";
        // 密钥
        String key = "love";
        // 加密后的内容
        String content = encode(message,key);
        // 解密还原
        String origin = decode(content,key);
        // 输出
        System.out.println("加密前：" + message);
        System.out.println("加密后：" + content);
        System.out.println("还原后：" + origin);
    }

    private static String encode(String message, String key) {
        // 将字符串转换为字母数组
        char[] messageChars = message.toLowerCase().toCharArray();
        char[] keyChars = key.toCharArray();
        // 利用密钥生成和待加密字符串对应长度的字符串
        StringBuffer encodeString = new StringBuffer();
        for (int i = 0; i < messageChars.length; i++) {
            String kk = String.valueOf(messageChars[i]);
            if(DICT.containsKey(kk)){
                // 如果是字母，进行加密
                // 得出待加密字符的数字
                Integer num = DICT.get(String.valueOf(messageChars[i]));
                // 计算对应的加密字符，比如`Hello`中的H，对应的是`l`，e对应的是o
                char kChar = keyChars[i % key.length()];
                // 取出对应加密字符的数字，计算与a的距离，a对应的数字是1。k即距离
                int k =  DICT.get(String.valueOf(kChar)) - 1;
                // 加密字符的数字加上距离k，得出加密后的数字
                int sec = num + k;
                // 如果小于10，补零，不然之后无法解密
                if(sec < 10){
                    encodeString.append("0"+sec);
                }else{
                    encodeString.append(sec);
                }
            }else{
                // 如果不是字母，直接拼接
                encodeString.append(String.valueOf(messageChars[i]));
            }
        }
        // 返回加密结果
        return encodeString.toString();
    }

    private static String decode(String message,String key){
        char[] msgChars = message.toCharArray();
        char[] keyChars = key.toCharArray();
        List<String> list = new ArrayList<>();
        for (int i = 0; i < msgChars.length; i++) {
            try{
                Integer.valueOf(String.valueOf(msgChars[i]));
                list.add(String.valueOf(msgChars[i]) + String.valueOf(msgChars[i+1]));
                i++;
            }catch (Exception ex){
                list.add(String.valueOf(msgChars[i]));
            }
        }

        StringBuffer decode = new StringBuffer();
        for (int i = 0; i < list.size(); i++) {
            if(list.get(i).length()>1){
                Integer num = Integer.valueOf(list.get(i));
                char thisKey = keyChars[i % keyChars.length];
                int k = DICT.get(String.valueOf(thisKey)) - 1;
                int sec = num - k;
                decode.append(getKeyByValue(sec));
            }else{
                decode.append(list.get(i));
            }
        }

        return decode.toString();
    }

    private static String getKeyByValue(Integer value){
        for (Map.Entry<String, Integer> stringIntegerEntry : DICT.entrySet()) {
            if(stringIntegerEntry.getValue() == value){
                return stringIntegerEntry.getKey();
            }
        }
        return null;
    }


}
